<?php
namespace frame\libs;
use \PDO;
use \Exception;
use \PDOException;
use frame\libs\Config;

/**
 * 包装PDO类
 */
final class PDOWrapper
{
    private $pdo = null;
    private $db_type;
    private $db_host;
    private $db_port;
    private $db_user;
    private $db_pass;
    private $db_name;
    private $charset; 

    public function __construct($dbName='')
    {
        $this->db_type = Config::get('type', 'database'); 
        $this->db_host = Config::get('hostname', 'database');
        $this->db_port = Config::get('hostport', 'database');
        $this->db_user = Config::get('username', 'database');
        $this->db_pass = Config::get('password', 'database');
        $this->db_name = $dbName!='' ? $dbName : Config::get('database', 'database');
        $this->charset = Config::get('charset', 'database');
        $this->createPDO();
        $this->setErrMode(); //设置报错模式
    }

    private function createPDO()
    {
        try {
            $dsn = "{$this->db_type}:host={$this->db_host};port={$this->db_port};dbname={$this->db_name};charset={$this->charset}";
            $this->pdo = new PDO($dsn, $this->db_user, $this->db_pass);
        } catch (Exception $e) {
            $this->showErrMsg($e);
            die();
        }
        
    }

    private function setErrMode()
    {
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    private function showErrMsg($e)
    {
        echo "<h2>数据库操作失败</h2>";
        echo "<br>错误编号：".$e->getCode();
        echo "<br>错误文件：".$e->getFile();
        echo "<br>错误行号：".$e->getLine();
        echo "<br>错误信息：".$e->getMessage();
        die();
    }

    public function fetchOne($sql, $params=array())
    {
    	if (empty($params)) {
    		$PDOStatement = $this->pdo->query($sql);
        	return $PDOStatement->fetch(PDO::FETCH_ASSOC);
    	}else{
    		$PDOStatement = $this->pdo->prepare($sql);
            $arr = array();
            foreach ($params as $key => $value) {
                $arr[":$key"] = $value;
            }
            $PDOStatement->execute($arr);
            return $PDOStatement->fetch(PDO::FETCH_ASSOC);
    	}
    }

    public function fetchAll($sql, $params=array())
    {
    	if (empty($params)) {
    		$PDOStatement = $this->pdo->query($sql);
        	return $PDOStatement->fetchAll(PDO::FETCH_ASSOC);
    	}else{
            $PDOStatement = $this->pdo->prepare($sql);
            $arr = array();
            foreach ($params as $key => $value) {
                $arr[":$key"] = $value;
            }
            $PDOStatement->execute($arr);
            return $PDOStatement->fetchAll(PDO::FETCH_ASSOC);
        }
    }

    public function exec($sql, $params=array())
    {
    	if (empty($params)) {
    		return $this->pdo->exec($sql);
    	}else{
            $PDOStatement = $this->pdo->prepare($sql);
            $arr = array();
            foreach ($params as $key => $value) {
                $arr[":$key"] = $value;
            }
            return $PDOStatement->execute($arr);
        }
    }

    public function rowCount($sql, $params=array())
    {
    	if (empty($params)) {
    		$PDOStatement = $this->pdo->query($sql);
        	return $PDOStatement->rowCount();
    	}else{
            $PDOStatement = $this->pdo->prepare($sql);
            $arr = array();
            foreach ($params as $key => $value) {
                $arr[":$key"] = $value;
            }
            $PDOStatement->execute($arr);
            return $PDOStatement->rowCount();
        }
    }

    public function lastInsertId()
    {
        return $this->pdo->lastInsertId();
    }

    public function beginTransaction()
    {
        return $this->pdo->beginTransaction();
    }

    public function commit()
    {
        return $this->pdo->commit();
    }

    public function rollBack()
    {
        return $this->pdo->rollBack();
    }
}